home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / macintosh-c / macc-carbon-demos-nonbinhex.sit / macc-carbon-demos-nonbinhex / chap23-demo-classic events / StartAndTrackDrag.c < prev    next >
Text File  |  2001-05-31  |  11KB  |  384 lines

  1. // *******************************************************************************************
  2. // StartAndTrackDrag.c
  3. // *******************************************************************************************
  4.  
  5. // ………………………………………………………………………………………………………………………………………………………………………………………………………………………… includes
  6.  
  7. #include "Drag.h"
  8.  
  9. // …………………………………………………………………………………………………………………………………………………………………………………………………… global variables
  10.  
  11. Boolean    gCursorInContent, gCanAcceptItems, gCaretShowFlag;
  12. SInt16    gInsertPosition, gLastOffset, gCaretOffset;
  13. UInt32    gSystemCaretTime, gCaretStartTime;
  14.  
  15. extern Boolean    gRunningOnX;
  16.  
  17. // ******************************************************************************* doStartDrag
  18.  
  19. OSErr  doStartDrag(EventRecord *eventStrucPtr,RgnHandle hiliteRgnHdl,TEHandle textEditStrucHdl)
  20. {
  21.     OSErr                    osError;
  22.     DragReference    dragRef;
  23.     Rect                    originalHiliteRect, zeroedHiliteRect;
  24.     RgnHandle            maskRgnHdl;
  25.     Point                    offsetPoint;
  26.     QDErr                    qdError;
  27.     CGrafPtr            savedPortPtr;
  28.     GDHandle            saveDeviceHdl;
  29.     GWorldPtr            dragGWorldPtr = NULL;
  30.     PixMapHandle    dragPixMapHdl, windPixMapHdl;
  31.     RgnHandle            dragRgnHdl, tempRgnHdl;
  32.  
  33.     // ………………………………………………………………………………………………………………………………………………………………………………………………… create new drag
  34.  
  35.     if(osError = NewDrag(&dragRef))
  36.         return osError;
  37.  
  38.     // ………………………………………………………………………………………………………………………………………………………………………………………… add 'TEXT' flavour
  39.  
  40.     osError = AddDragItemFlavor(dragRef,1,'TEXT',
  41.                                                             (*(*textEditStrucHdl)->hText) + (*textEditStrucHdl)->selStart,
  42.                                                             (*textEditStrucHdl)->selEnd - (*textEditStrucHdl)->selStart,0);
  43.  
  44.  
  45.     // ……………………………………………………………………………………………… get and set drag image for translucent drag and drop
  46.  
  47.     if(!gRunningOnX)
  48.     {
  49.         maskRgnHdl =  dragRgnHdl = tempRgnHdl = NULL;
  50.  
  51.         GetRegionBounds(hiliteRgnHdl,&originalHiliteRect);
  52.         zeroedHiliteRect = originalHiliteRect;
  53.         OffsetRect(&zeroedHiliteRect,-originalHiliteRect.left,-originalHiliteRect.top);
  54.  
  55.         GetGWorld(&savedPortPtr,&saveDeviceHdl);
  56.  
  57.         qdError = NewGWorld(&dragGWorldPtr,8,&zeroedHiliteRect,NULL,NULL,0);
  58.         if(dragGWorldPtr != NULL && qdError == noErr)
  59.         {
  60.             SetGWorld(dragGWorldPtr,NULL);
  61.             EraseRect(&zeroedHiliteRect);
  62.  
  63.             dragPixMapHdl = GetGWorldPixMap(dragGWorldPtr);
  64.             LockPixels(dragPixMapHdl);
  65.             windPixMapHdl = GetGWorldPixMap(savedPortPtr);
  66.  
  67.             CopyBits((BitMap *) *windPixMapHdl,(BitMap *) *dragPixMapHdl,
  68.                              &originalHiliteRect,&zeroedHiliteRect,srcCopy,NULL);
  69.  
  70.             UnlockPixels(dragPixMapHdl);
  71.             SetGWorld(savedPortPtr,saveDeviceHdl);
  72.  
  73.             maskRgnHdl = NewRgn();
  74.             if(maskRgnHdl != NULL)
  75.             {
  76.                 CopyRgn(hiliteRgnHdl,maskRgnHdl);
  77.                 OffsetRgn(maskRgnHdl,-originalHiliteRect.left,-originalHiliteRect.top);
  78.  
  79.                 SetPt(&offsetPoint,originalHiliteRect.left,originalHiliteRect.top);
  80.                 LocalToGlobal(&offsetPoint);
  81.  
  82.                 SetDragImage(dragRef,dragPixMapHdl,maskRgnHdl,offsetPoint,kDragStandardTranslucency);
  83.             }
  84.         }
  85.     }
  86.  
  87.     // ………………………………………………………………………………………………………………………………………………………………………………………………… get drag region
  88.  
  89.     dragRgnHdl = NewRgn();
  90.     if(dragRgnHdl == NULL)
  91.         return MemError();
  92.  
  93.     CopyRgn(hiliteRgnHdl,dragRgnHdl);
  94.     SetPt(&offsetPoint,0,0);
  95.     LocalToGlobal(&offsetPoint);
  96.     OffsetRgn(dragRgnHdl,offsetPoint.h,offsetPoint.v);
  97.     
  98.     tempRgnHdl = NewRgn();
  99.     if(tempRgnHdl == NULL)
  100.         return MemError();
  101.  
  102.     CopyRgn(dragRgnHdl,tempRgnHdl);
  103.     InsetRgn(tempRgnHdl,1,1);
  104.     DiffRgn(dragRgnHdl,tempRgnHdl,dragRgnHdl);
  105.     DisposeRgn(tempRgnHdl);
  106.  
  107.     // ……………………………………………………………………………………………………………………………………………………………………………………………… perform the drag
  108.  
  109.     osError = TrackDrag(dragRef,eventStrucPtr,dragRgnHdl);
  110.     if(osError != noErr && osError != userCanceledErr)
  111.         return osError;
  112.  
  113.     if(dragRef)                DisposeDrag(dragRef);
  114.     if(maskRgnHdl)         DisposeRgn(maskRgnHdl);
  115.     if(dragGWorldPtr)    DisposeGWorld(dragGWorldPtr);
  116.     if(dragRgnHdl)         DisposeRgn(dragRgnHdl);
  117.     if(tempRgnHdl)         DisposeRgn(tempRgnHdl);
  118.  
  119.     return noErr;
  120. }
  121.  
  122. // *********************************************************************** dragTrackingHandler
  123.  
  124. OSErr dragTrackingHandler(DragTrackingMessage trackingMessage,WindowRef windowRef,
  125.                                                     void *handlerRefCon,DragRef dragRef)
  126. {
  127.     docStructurePointer    docStrucPtr;
  128.     DragAttributes            dragAttributes;
  129.     UInt32                            theTime;
  130.     UInt16                            numberOfDragItems, index;
  131.     ItemReference                itemRef;
  132.     OSErr                                result;
  133.     FlavorFlags                    flavorFlags;
  134.     Point                                mousePt, localMousePt;    
  135.     RgnHandle                        windowHiliteRgn;
  136.     Rect                                correctedViewRect;
  137.     SInt16                            theOffset;
  138.  
  139.     if((trackingMessage != kDragTrackingEnterHandler) && !gCanAcceptItems)
  140.         return noErr;
  141.  
  142.     docStrucPtr = (docStructurePointer) handlerRefCon;        
  143.  
  144.     GetDragAttributes(dragRef,&dragAttributes);
  145.     gSystemCaretTime = GetCaretTime();
  146.     theTime = TickCount();
  147.     
  148.     switch(trackingMessage)
  149.     {
  150.         // ………………………………………………………………………………………………………………………………………………………………………………………………… enter handler
  151.  
  152.         case kDragTrackingEnterHandler:
  153.             gCanAcceptItems = true;
  154.  
  155.             CountDragItems(dragRef,&numberOfDragItems);
  156.  
  157.             for(index=1;index <= numberOfDragItems;index++)
  158.             {
  159.                 GetDragItemReferenceNumber(dragRef,index,&itemRef);
  160.                 result = GetFlavorFlags(dragRef,itemRef,'TEXT',&flavorFlags);
  161.                 if(result != noErr)
  162.                 {
  163.                     gCanAcceptItems = false;
  164.                     break;
  165.                 }
  166.             }
  167.             break;
  168.  
  169.             // ……………………………………………………………………………………………………………………………………………………………………………………………… enter window
  170.  
  171.         case kDragTrackingEnterWindow:
  172.             gCaretStartTime  = theTime;
  173.             gCaretOffset     = gLastOffset = -1;
  174.             gCaretShowFlag   = true;
  175.             gCursorInContent = false;
  176.             break;
  177.  
  178.         // …………………………………………………………………………………………………………………………………………………………………………………………………………… in window
  179.  
  180.         case kDragTrackingInWindow:
  181.  
  182.             GetDragMouse(dragRef,&mousePt,NULL);
  183.             localMousePt = mousePt;
  184.             GlobalToLocal(&localMousePt);
  185.  
  186.             if(dragAttributes & kDragHasLeftSenderWindow)
  187.             {
  188.                 if(PtInRect(localMousePt,&(**(docStrucPtr->textEditStrucHdl)).viewRect))
  189.                 {
  190.                     if(!gCursorInContent)
  191.                     {
  192.                         windowHiliteRgn = NewRgn();
  193.                         correctedViewRect = (**(docStrucPtr->textEditStrucHdl)).viewRect;
  194.                         InsetRect(&correctedViewRect,-2,-2);
  195.                         RectRgn(windowHiliteRgn,&correctedViewRect);
  196.                         ShowDragHilite(dragRef,windowHiliteRgn,true);
  197.                         DisposeRgn(windowHiliteRgn);
  198.                     }
  199.                     gCursorInContent = true;
  200.                 }
  201.                 else
  202.                 {
  203.                     if(gCursorInContent)
  204.                         HideDragHilite(dragRef);
  205.                     gCursorInContent = false;
  206.                 }
  207.             }
  208.  
  209.             // … … … … … … … … … … … … start caret drawing stuff, first get the offset into the text
  210.  
  211.             theOffset = doGetOffset(mousePt,docStrucPtr->textEditStrucHdl);
  212.             
  213.             // … … … … … … … … … … … … … … …  if in sender window, defeat caret drawing in selection
  214.  
  215.             if(dragAttributes & kDragInsideSenderWindow)
  216.             {
  217.                 if((theOffset >= (*(docStrucPtr->textEditStrucHdl))->selStart) &&
  218.                      (theOffset <= (*(docStrucPtr->textEditStrucHdl))->selEnd))
  219.                 {
  220.                     theOffset = -1;
  221.                 }
  222.             }
  223.  
  224.             // … … … … … … … … … … … … … … save the offset to a global for use by dragReceiveHandler
  225.  
  226.             gInsertPosition = theOffset;
  227.  
  228.             // … … … … … … … … … … … … … … … … if offset has changed, reset the caret flashing timer
  229.  
  230.             if(theOffset != gLastOffset)
  231.             {
  232.                 gCaretStartTime = theTime;
  233.                 gCaretShowFlag = true;
  234.             }
  235.  
  236.             gLastOffset = theOffset;
  237.  
  238.             // … … … … if caret-flashing interval has elapsed, toggle caret "show" flag, reset timer
  239.  
  240.             if(theTime - gCaretStartTime > gSystemCaretTime)
  241.             {
  242.                 gCaretShowFlag = !gCaretShowFlag;
  243.                 gCaretStartTime = theTime;
  244.             }
  245.  
  246.             // … … … … … … … … … … if caret "show" flag is off, set variable to defeat caret drawing
  247.  
  248.             if(!gCaretShowFlag)
  249.                 theOffset = -1;
  250.  
  251.             // … … … … if offset has changed, erase previous caret, draw new caret at current offset
  252.  
  253.             if(theOffset != gCaretOffset)
  254.             {
  255.                 // … … … … … … … if first pass this window, don't erase, otherwise erase at old offset
  256.  
  257.                 if(gCaretOffset != -1)
  258.                     doDrawCaret(gCaretOffset,docStrucPtr->textEditStrucHdl);
  259.  
  260.                 // … … … … … … …  … … …  … … …  if "show" flag says show, draw caret at current offset
  261.  
  262.                 if(theOffset != -1)
  263.                     doDrawCaret(theOffset,docStrucPtr->textEditStrucHdl);
  264.             }
  265.  
  266.             gCaretOffset = theOffset;
  267.  
  268.             break;
  269.  
  270.         // …………………………………………………………………………………………………………………………………………………………………………………………………… leave window
  271.  
  272.         case kDragTrackingLeaveWindow:
  273.  
  274.             if(gCaretOffset != -1)
  275.             {
  276.                 doDrawCaret(gCaretOffset,docStrucPtr->textEditStrucHdl);
  277.                 gCaretOffset = -1;
  278.             }
  279.  
  280.             if(gCursorInContent && dragAttributes & kDragHasLeftSenderWindow)
  281.                 HideDragHilite(dragRef);
  282.  
  283.             break;
  284.  
  285.         // ………………………………………………………………………………………………………………………………………………………………………………………………… leave handler
  286.  
  287.         case kDragTrackingLeaveHandler:
  288.             break;
  289.     }
  290.  
  291.     return noErr;
  292. }
  293.  
  294. // ******************************************************************************* doGetOffset
  295.  
  296. SInt16  doGetOffset(Point mousePt,TEHandle textEditStrucHdl)
  297. {
  298.     WindowRef    windowRef;
  299.     SInt16        theOffset;
  300.     Point            thePoint;
  301.  
  302.     theOffset = -1;
  303.  
  304.     if(FindWindow(mousePt,&windowRef) == inContent)
  305.     {
  306.         SetPortWindowPort(windowRef);
  307.         GlobalToLocal(&mousePt);
  308.  
  309.         if(PtInRect(mousePt,&((*textEditStrucHdl)->viewRect)))
  310.         {
  311.             theOffset = TEGetOffset(mousePt,textEditStrucHdl);
  312.             thePoint    = TEGetPoint(theOffset - 1,textEditStrucHdl);
  313.  
  314.             if((theOffset) &&
  315.                  (doIsOffsetAtLineStart(theOffset,textEditStrucHdl)) &&
  316.                  ((*(*textEditStrucHdl)->hText)[theOffset - 1] != 0x0D) &&
  317.                  (thePoint.h < mousePt.h))
  318.             {
  319.                 theOffset--;
  320.             }
  321.         }
  322.     }
  323.  
  324.     return theOffset;
  325. }
  326.  
  327. // ********************************************************************* doIsOffsetAtLineStart
  328.  
  329. SInt16  doIsOffsetAtLineStart(SInt16 offset,TEHandle textEditStrucHdl)
  330. {
  331.     SInt16    line = 0;
  332.  
  333.     if((*textEditStrucHdl)->teLength == 0)
  334.         return(true);
  335.  
  336.     if(offset >= (*textEditStrucHdl)->teLength)
  337.         return((*((*textEditStrucHdl)->hText))[(*textEditStrucHdl)->teLength - 1] == 0x0D);
  338.  
  339.     while((*textEditStrucHdl)->lineStarts[line] < offset)
  340.         line++;
  341.  
  342.     return ((*textEditStrucHdl)->lineStarts[line] == offset);
  343. }
  344.  
  345. // ******************************************************************************* doDrawCaret
  346.  
  347. void  doDrawCaret(SInt16 theOffset,TEHandle textEditStrucHdl)
  348. {
  349.     Point        thePoint;
  350.     SInt16    theLine, lineHeight;
  351.  
  352.     thePoint = TEGetPoint(theOffset,textEditStrucHdl);
  353.     theLine  = doGetLine(theOffset,textEditStrucHdl);
  354.  
  355.     if((theOffset == (*textEditStrucHdl)->teLength) &&
  356.             (*((*textEditStrucHdl)->hText))[(*textEditStrucHdl)->teLength - 1] == 0x0D)
  357.     {
  358.         thePoint.v += TEGetHeight(theLine,theLine,textEditStrucHdl);
  359.     }
  360.  
  361.     PenMode(patXor);
  362.     lineHeight = TEGetHeight(theLine,theLine,textEditStrucHdl);
  363.     MoveTo(thePoint.h - 1,thePoint.v - 1);
  364.     Line(0,1 - lineHeight);
  365.  
  366.     PenNormal();
  367. }
  368.  
  369. // ********************************************************************************* doGetLine
  370.  
  371. SInt16  doGetLine(SInt16 theOffset,TEHandle textEditStrucHdl)
  372. {
  373.     SInt16    theLine = 0;
  374.  
  375.     if(theOffset > (*textEditStrucHdl)->teLength)
  376.         return ((*textEditStrucHdl)->nLines);
  377.  
  378.     while((*textEditStrucHdl)->lineStarts[theLine] < theOffset)
  379.         theLine++;
  380.  
  381.     return theLine;
  382. }
  383.  
  384. // *******************************************************************************************